#ifndef LBSERVER_H
#define LBSERVER_H

#include "../include/global.h"
#include "config.h"
#include "rs.h"
#include "resourceManager.h"

class SpreadMessageInfo{
	public:
		SpreadMessageInfo(unsigned int sourceRs,unsigned int fileId,unsigned int destRs){
			_fileId = fileId;
			_sourceRs = sourceRs;
			_destRs = destRs;
			inSpread = false;
		}
	public:
		unsigned int _fileId;
		unsigned int _sourceRs;
		unsigned int _destRs;
		bool inSpread;
};


class RS;
class ResourceManager;
class LBServer{
	public:
		LBServer(ServerConfigType *serverConfig);
		~LBServer();
	public:
		void run();
	public: //for content service
		int startContentService(string serverPort);
		void messageHandler(int sockfd);
		int downloadFile(unsigned int clientId,unsigned int rsId,unsigned int fileId,unsigned int clientBandwidth);
		unsigned int findBestRs(unsigned int fileId);
		unsigned int findBestDest(vector<bool> &canChooseRs,unsigned int spreadFileId);
	public: //for resource spread
		int needSpread(unsigned int rsId,const vector<unsigned int> &fileList);
		bool isInSpreadFile(unsigned int fileId);
		bool isInSpreadSource(unsigned int sourceId);
		bool isInSpreadDest(unsigned int destId);
		bool checkSpreadMessage(SpreadMessageInfo * spreadMessage);
		int addSpreadMessage(SpreadMessageInfo * spreadMessage);
		int deleteSpreadMessage(unsigned int sourceRs,unsigned int fileId,unsigned int destRs);
		int resourceSpreadHandler();
		int getRSSet(unsigned int fileId,vector<unsigned int> &rsset);
	public: //for statistical
		void doStatistical();
		void resetAllCount();
		void increaseClientNumber();
		unsigned int getClientNumber();
		void printRSInfo();
	public:
		int addNewFile(unsigned int rsId,unsigned int fileId);
		void initRSList();
		int requestFile(unsigned int sourceRs,unsigned int fileId,unsigned int destRs);
	private:
		pthread_mutex_t _lbmutex;
		pthread_cond_t _needSpread;
		vector<SpreadMessageInfo* > spreadMessageQueue;
		//vector<FileInfo*> _fileList;
		vector< RS* > _rsList;
		unsigned int clientNumber;	
	private:
		//Scheduler *_scheduler;
		ResourceManager *resourceManager;
		ServerConfigType * _serverConfig;
		unsigned int _resourceNumber;
		unsigned int _rsNumber;
};

class reqHandlerArg{
	public:
		reqHandlerArg(LBServer *server,int sockfd){
			_server = server;
			_sockfd = sockfd;
		}
		LBServer *_server;
		int _sockfd;
};

class spreadHandlerArg{
	public:
		spreadHandlerArg(LBServer *server,unsigned int sourceRs,unsigned int fileId,unsigned int destRs){
			_server = server;
			_sourceRs = sourceRs;
			_fileId = fileId;
			_destRs = destRs;
		}
		LBServer *_server;
		unsigned int _sourceRs,_fileId,_destRs;
};
#endif
